import React, { Component, Fragment } from 'react';
import {
    Row,
    Col,
    Card,
    Input,
    Select,
    Icon,
    Button,
    Dropdown,
    InputNumber,
    DatePicker,
    Alert,
    Table,
    Typography,
    Tooltip
} from 'antd';
import styles from './index.less';
import { isFunction } from 'util';
import AdvancedSearch from '@/components/AdvancedSearch';
import UUID from 'uuid';

const { Text } = Typography;
const UNCHANGE_MARK = "$$";
const ACTIVE_OBJ = "searchBtn";

// 获得记录的ID或者id
function mid(record) {
    return record.id? record.id: (record.ID? record.ID: -1);
}

// Map to list 转换
function map2List(map, func = "values") {
    let it = map[func](), pointer, cache = [];
    while(!(pointer = it.next()).done) {
        cache.push(pointer.value);
    }
    return cache;
}

// 产生合法的列字典
function genCols(curCols) {
    curCols = curCols.filter(c => !c.dataIndex.startsWith(UNCHANGE_MARK));
    let names = [];
    for (let col of curCols) {
        names.push({ [col.dataIndex]: col.title });
    }
    return names;
}

// 产生条件选项
function genSearchConds(items, order, outterRef) {
    let conditions = [];
    for (let item of items) {
        if (item.datatable &&
            (item.first || item.isExtent) &&
            item.key &&
            item.value) {
            conditions.push({
                dataTable: item.datatable,
                name: item.key,
                value: item.value,
                mode: item.mode ? item.mode : 0
            });
        }
    }
    if (!order.field) order = {};
    if (!Array.isArray(outterRef)) outterRef = [];
    return {
        conditions: conditions,
        order: order,
        relations: outterRef
    }
}

/**
 * 高级表
 * 修改以下代码必须十分小心，本表格的实现方式是采用分页查询的方式
 * 换页或调整页大小的时候都会触发刷新页面，但请求的数据量只有当页的数据(分页查询)
 * 
 * 注意事项：数据条目中必须包含主键ID/id, 不然无法对其做跨页筛选
 * 数据条目的唯一性通过ID进行判断 - 要求所有数据条目必须含有ID作为标识
 * 
 * @author 戴舒原 2019-03-01
 */
export default class AdvancedTable extends Component {
    constructor(props) {
        super(props);
        this.useMultiSelect = this.props.useMultiSelect;                                // 是否支持多选
        this.controllers = Array.isArray(props.controllers) ? props.controllers : [];   // 上边栏控制按钮
        let columns = Array.isArray(props.columns) ? props.columns : [];                // 全部列
        this.op_cols = columns.filter(c => c.dataIndex.startsWith(UNCHANGE_MARK));      // 操作列(特殊列)
        this.selectAllFlag = false;                                                     // 全选标志（默认不全选）
        this.selectRows = new Map();                                                    // 选中行或未选中行
        this.master = this.props.master;                                                // 主表
        this.items = this.props.items;                                                  // 检索条件
        this.pageNum = 1;                                                               // 页码
        this.pageSize = 10;                                                             // 页内元素数目
        this.total = 0;                                                                 // 全部数据条目
        this.outterRef = this.props.outterRef;                                          // 外键引用
        this.orderField = null;                                                         // 排序字段
        this.orderMode = null;                                                          // 排序模式
        this.columnsMap = new Map();                                                    // 构建快速选择Map
        this.dataProc = this.props.dataProc;                                            // 拉取数据后处理函数
        this.dataPreProc = this.props.dataPreProc;                                      // 查询数据前处理函数
        for (let col of columns) {
            this.columnsMap.set(col.dataIndex, col);
        }
        this.controllers.forEach(x => x.id = UUID.v4());
        let loadings = {};                                                              // 按钮加载状态
        this.controllers.forEach(x => loadings[x.id] = false);
        this.state = {
            datalines: [],                                                              // 加载的单页数据
            loading: false,                                                             // 加载状态
            selectedRowKeys: [],                                                        // 默认选择行
            currentColumns: columns.filter((c) => c.first || c.dataIndex.startsWith(UNCHANGE_MARK)), // 有效数据列
            updateCount: !!this.props.updateFirst? 1: 0,                                // 初始化数据刷新
            superCol: false,
            ...loadings
        };
        if (this.props.hasOwnProperty("showSearcher")) {
            this.showSearcher = this.props.showSearcher;                                // 是否展示检索内容
        } else{
            this.showSearcher = true;                                                   // 默认显示高级检索
        }
    }

    // 当表格排序顺序改变时触发
    handleTableChange = (_, __, sorter) => {
        this.orderField = sorter.field;
        this.orderMode = (sorter.order === "ascend")? true: false;
        this.setState({ updateCount: this.state.updateCount + 1 });
    };

    // 生成表尾部
    genFooter = () => {
        return (<Row type="flex" justify="end">
                    <Col xs={24} sm={24} md={24} lg={24} xl={24} style={{ textAlign: "right" }}>
                        共计 <Text strong> { this.total }</Text> 条 
                    </Col>
                </Row>);
    }

    // 向外部传递一个可以控制表格的句柄
    makeHandle = (controller) => {
        return {
            dataTable: this.master,
            selectAll: this.useMultiSelect? this.selectAllFlag: true,
            selectedRows: map2List(this.selectRows),
            selectedIndics: map2List(this.selectRows, "keys"),
            selectedCols: genCols(this.state.currentColumns),
            pageNum: this.pageNum,
            pageSize: this.pageSize,
            // 生成检索条件
            ...genSearchConds(this.items, {
                field: this.orderField,
                mode: this.orderMode
            }, this.outterRef),
            // 显示Loading状态
            showLoad: (bool) => {
                const loading = this.state[controller.id];
                (bool != loading) && this.setState({[controller.id]: bool});
            },
            // 更新列表
            updateList: () => {
                this.setState({
                    updateCount: this.state.updateCount + 1
                });
            }
        };
    }

    // 生成表头部
    genHeader = () => {
        // 生成可见栏目
        const colMap = this.columnsMap;
        const opList = Array.isArray(this.op_cols)? this.op_cols: [];
        let cache = [], def = [];
        for (let col of this.props.columns) {
            if (!col.dataIndex.startsWith(UNCHANGE_MARK)) {
                cache.push(<Select.Option value={col.dataIndex}>{col.title}</Select.Option>);
            }
        }

        // 生成操作栏目
        for (let col of this.state.currentColumns) {
            if (!col.dataIndex.startsWith(UNCHANGE_MARK)) {
                def.push(col.dataIndex);
            }
        }

        // 生成表格高级选项组件
        const xlw = 2;
        let len = this.controllers.length;
        let full = 22 - xlw * len, controllers = [];
        for (let controller of this.controllers) {
            let loading = this.state[controller.id];
            controllers.push(
                <Col xs={Math.floor(24 / len)} sm={12 / len} md={12 / len} lg={xlw * 2} xl={xlw}>
                    <Button loading={loading} onClick = {() => {
                        isFunction(controller.callback) && controller.callback(this.makeHandle(controller));
                    }} type="primary">
                        { controller.icon && !loading ? <Icon type={controller.icon} />: "" }
                        { controller.name }
                    </Button>
                </Col>);
        }

        // 生成高级列扩展
        const superCol = this.state.superCol;
        return (
            <Row type="flex" align="middle">
                <Col xs={4} sm={4} md={2} lg={2} xl={1} style={{paddingBottom: "0.3rem"}}>
                    <Tooltip title="表格高级选项">
                        <Button type="dashed"
                            icon={superCol? "caret-right": "caret-down"} onClick={() => {
                            this.setState({superCol: !superCol});
                        }}></Button>
                    </Tooltip>
                </Col>
                <Col xs={full} sm={full} md={full} lg={full} xl={full} style={{
                    paddingBottom: "0.3rem",
                    paddingLeft: "0.1rem"
                }}>
                    {!superCol? "": 
                    <Select
                        style={{ minWidth: "150px" }}
                        mode="multiple"
                        defaultValue={def}
                        onChange={(e, list) => {
                            list = list.map(x => colMap.get(x.props.value));
                            this.setState({ currentColumns: list.concat(opList) });
                        }}>{cache}
                    </Select>}
                </Col>
                <Col xs={1} sm={1} md={1} lg={1} xl={1}></Col>
                {controllers}
            </Row>);
    }

    // 判断是否未选择列
    isColumnVoid = () => {
        // 未选择任何列时清空列表
        let cols = this.state.currentColumns;
        if (Array.isArray(cols) && cols.length > 0) {
            let changes = cols.filter(x =>
                x.dataIndex && !x.dataIndex.startsWith(UNCHANGE_MARK)
            );
            if (changes.length > 0) return false;
            this.state.currentColumns.length = 0;
        }
        return true;
    }

    // 控制多选的选中状态
    controlSelectStatus = (list, pageSize) => {
        // 在换页时记录
        const selectRows = this.selectRows;
        let selectedRowKeys = [];
        for (let i = 0; i < pageSize && i < list.length; ++i) {
            let item = list[i];
            if (this.selectAllFlag !== (selectRows.has(item.id) || selectRows.has(item.ID))) {
                selectedRowKeys.push(i);
            }
        }
        this.setState({ selectedRowKeys: selectedRowKeys });
    }

    // 拉取数据前
    beforeGetDataLines = (obj, searchConds) => {
        if (obj === ACTIVE_OBJ) {
            // 当点击查询按钮时回退到第一页
            searchConds.pageNum = this.pageNum = 1;
            // 清空选择项
            this.selectRows.clear();
        }
        isFunction(this.dataPreProc) && this.dataPreProc(searchConds);
        this.setState({ loading: true });
    }

    // 拉取数据后
    afterGetDataLines = (list, count) => {
        let cache_list = list;
        let cache_count = count;
        // 提供一个方法用于进行拉取数据处理
        if (isFunction(this.dataProc)) {
            let obj = this.dataProc(list, count);
            if(obj && obj.result && obj.count) {
                cache_list = obj.result;
                cache_count = obj.count;
            }
        }
        this.total = cache_count;
        this.controlSelectStatus(cache_list, this.pageSize);
        this.setState({
            datalines: cache_list,
            loading: false
        });
    }

    render() {
        let rowSelection = false;
        const { selectedRowKeys } = this.state;
        const { rowKey, ...rest } = this.props;
        const list = this.state.datalines;

        // 分页控制
        const paginationProps = {
            showSizeChanger: true,
            showQuickJumper: true,
            defaultCurrent: this.pageNum,
            total: this.total,
            current: this.pageNum,
            pageSize: this.pageSize,
            onChange: (current, pageSize) => {
                this.pageNum = current;
                this.pageSize = pageSize;
                this.setState({ updateCount: this.state.updateCount + 1 });
            },
            onShowSizeChange: (current, pageSize) => {
                this.pageNum = current;
                this.pageSize = pageSize;
                this.setState({ updateCount: this.state.updateCount + 1 });
            }
        };

        // 操作数据填充
        for (let op of this.op_cols) {
            for (let dataline of list) {
                dataline[op.dataIndex] = { ...dataline, getHandle: () => this.makeHandle() };
            }
        }

        // 表格多选
        if (this.useMultiSelect) {
            rowSelection = {
                selectedRowKeys,
                onChange: (selectedRowKeys) => {
                    this.setState({ selectedRowKeys });
                },
                onSelect: (record, selected) => {
                    if (selected !== this.selectAllFlag) {
                        this.selectRows.set(mid(record), record);
                    } else {
                        this.selectRows.delete(mid(record));
                    }
                },
                getCheckboxProps: record => ({
                    disabled: record.disabled,
                }),
                onSelectAll: (selected) => {
                    this.selectRows.clear();
                    this.selectAllFlag = selected;
                },
            };
        }

        return (
            <div className={ styles.standardTable }>
               {this.showSearcher? <AdvancedSearch
                    orderField = { this.orderField }
                    orderMode = { this.orderMode }
                    pageNum = { this.pageNum }
                    pageSize = { this.pageSize }
                    master = { this.master } 
                    items = { this.items }
                    outterRef = { this.outterRef }
                    beforeCallback = { this.beforeGetDataLines }
                    callback = { this.afterGetDataLines }
                    updateCount = { this.state.updateCount } />: ""}
                <Table
                    loading = { this.state.loading }
                    title = { this.genHeader }
                    footer = { this.genFooter }
                    rowKey = { rowKey || 'key' }
                    rowSelection = { rowSelection }
                    dataSource = { this.isColumnVoid() ? [] : list }
                    pagination = { paginationProps }
                    onChange = { this.handleTableChange }
                    { ...rest }
                    columns = { this.state.currentColumns }
                />
            </div>
        );
    }
}